/*******************************************************************************
 * @file    bsp_inflash.c
 * @author  Harm
 * @version V1.00
 * @date    21-May-2022
 * @brief   ......
*******************************************************************************/


/* Define to prevent recursive inclusion -------------------------------------*/
#define __BSP_INFLASH_C__


/* Includes ------------------------------------------------------------------*/
#include "bsp_inflash.h"

#if INFLASH_ENABLE

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/


/* Private variables ---------------------------------------------------------*/


/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/


/* Exported variables --------------------------------------------------------*/
/* Exported function prototypes ----------------------------------------------*/

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
int InFlashReadBytes(uint32_t Addr,uint8_t *pBuf,uint32_t size)
{
	unsigned int i;
	
	if(size == 0) return FALSE;
	
	for(i=0;i<size;i++)
	{
		pBuf[i] = *(volatile unsigned char *) (Addr + i);
	}
	return TRUE;
	
}

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   //用该函数前，请先擦除相关的页面,不单独使用
*******************************************************************************/
static void _InFlashWriteBytes(uint32_t Addr,uint8_t *pBuf,uint32_t size)
{
	unsigned int iWrite = 0;
	unsigned int WriteAddr = Addr;
	unsigned int *pWriteData =(unsigned int *) pBuf;
	
	for(iWrite = 0 ;iWrite < size/4;iWrite ++)
	{
		FLASH_ProgramWord(WriteAddr, *pWriteData);
		WriteAddr = WriteAddr + 4;
		pWriteData ++;
	}
	
	
	if(size % 4 == 0)
	{
		//不用处理
	}
	else if(size % 4 == 1)
	{
		FLASH_ProgramWord(WriteAddr, (*pWriteData + 0xFFFFFF00));
	}
	else if(size % 4 == 2)
	{
		FLASH_ProgramWord(WriteAddr, (*pWriteData + 0xFFFF0000));
	}
	else if(size % 4 == 3)
	{
		FLASH_ProgramWord(WriteAddr, (*pWriteData + 0xFF000000));
	}
	

}

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
unsigned char StmFlashBuf[FLASH_PAGE_SIZE];//页数据拷贝临时缓冲区
int InFlashWriteBytes(uint32_t Addr,uint8_t *pBuf,uint32_t size)
{
  unsigned int PageAddr = Addr & (~(FLASH_PAGE_SIZE-1));//取出页面地址
	unsigned char *pBuffer = pBuf;
	
	if(size == 0 ) return TRUE;
	
	if((Addr%FLASH_PAGE_SIZE+size)>FLASH_PAGE_SIZE)
	{
		unsigned int slen = FLASH_PAGE_SIZE - Addr%FLASH_PAGE_SIZE;
		InFlashWriteBytes(Addr+slen,pBuf+slen,size-slen);
		size = slen;	
	}
	
	InFlashReadBytes(PageAddr,StmFlashBuf,FLASH_PAGE_SIZE);
	memcpy(StmFlashBuf+Addr%FLASH_PAGE_SIZE,pBuf,size);
	pBuffer = StmFlashBuf;
	
	FLASH_Unlock();
	FLASH_ClearFlag(FLASH_FLAG_BSY |FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
	FLASH_ErasePage(PageAddr);
	_InFlashWriteBytes(PageAddr,pBuffer,FLASH_PAGE_SIZE);
	
	FLASH_Lock();
	
	return TRUE;
	
}

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void shell_Inflash_Write_cmd(char argc, char *argv)
{
	uint32_t address;
	uint8_t *data;
	uint8_t length;
	char *param;
	
	if(argc<4)
	{
		printf("Error Command! Usage (such as):flashw address data length\r\n");
		printf("adress:[0~%d*1024]\r\n",USER_ALLOW_FLASH_REGIO_SIZE);
		printf("User available flash size %dk\r\n",USER_ALLOW_FLASH_REGIO_SIZE);
		goto END;
	}
	
	param = &(argv[argv[1]]);
	address = atoi(param);
	
	
	param = &(argv[argv[2]]);
	data = (uint8_t *)param;
	
	param = &(argv[argv[3]]);
	length = atoi(param);
	
	StmInFlash_WriteBytes(address,data,length);

	printf("write ok! address = 0x%x,data = %s\r\n",FLASH_USER_ADDR + address,data);

END:
		;
} 

/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void shell_Inflash_Read_cmd(char argc, char *argv)
{
#if 1
	uint32_t address;
	uint32_t length;
	uint8_t databuf[128] = {0};
	char *param ;
	
	if(argc < 3)
	{
		printf("Error Command! Usage (such as):flashr address length\r\n");
		printf("adress:[0~%d*1024]\r\n",USER_ALLOW_FLASH_REGIO_SIZE);
		printf("User available flash size %dk\r\n",USER_ALLOW_FLASH_REGIO_SIZE);
		goto END;
	}
	
	param = &(argv[argv[1]]);
	address = atoi(param);
	
	param = &(argv[argv[2]]);
	length = atoi(param);
	
	StmInFlash_ReadBytes(address,databuf,length);
	printf("read ok! address = 0x%x,data = %s\r\n",FLASH_USER_ADDR + address,databuf);
#endif

END:
	;
	
} 


#endif
/******************* (C) COPYRIGHT 2022 END OF FILE****************************/

